<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>debounce</title>
</head>
<body>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <p>
        function showTop(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置：' + scrollTop);
        }
        function debounce(fn,delay){
        let timer = null //借助闭包
        return function() {
        if(timer){
        clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        timer = setTimeout(fn,delay)
        }else{
        timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        }
        }
        }

        window.onscroll  = debounce(showTop,200);

    </p>
    <script>
        function showTop(){
            var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
            console.log('滚动条位置：' + scrollTop);
        }
        // function debounce(fn,delay){
        //     let timer = null //借助闭包
        //     return function() {
        //         if(timer){
        //             clearTimeout(timer) //进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时
        //             timer = setTimeout(fn,delay)
        //         }else{
        //             timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        //         }
        //     }
        // }
        // function debounce2(fn,delay){
        //     let timer = null //借助闭包
        //     return function() {
        //         if(timer){
        //             clearTimeout(timer)
        //         }
        //         timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时，那么就开始一个计时
        //
        //     }
        // }
        // function throttle(fn,delay){
        //     let valid = true
        //     return function() {
        //         if(!valid){
        //             //休息时间 暂不接客
        //             return false
        //         }
        //         // 工作时间，执行函数并且在间隔期内把状态位设为无效
        //         valid = false
        //         setTimeout(() => {
        //             fn()
        //             valid = true;
        //         }, delay)
        //     }
        // }
        function throttle2 (func, wait) {
            let lastTime = null
            // 为了避免每次调用lastTime都被清空，利用js的闭包返回一个function确保不声明全局变量也可以
            return function () {
                let now = Date.now();
                // 如果上次执行的时间和这次触发的时间大于一个执行周期，则执行
                if (now - lastTime - wait > 0) {
                    func()
                    lastTime = now
                }
            }
        }


        function throttle3 (func, wait) {
            let lastTime = null
            let timeout = null
            return function () {
                let context = this
                let now = Date.now()
                // 如果上次执行的时间和这次触发的时间大于一个执行周期，则执行
                if (now - lastTime - wait > 0) {
                    // 如果之前有了定时任务则清除
                    if (timeout) {
                        clearTimeout(timeout)
                        timeout = null
                    }
                    func.apply(context, arguments)
                    // 这里lastTime是上次的触发时间
                    lastTime = now
                } else if (!timeout) {
                    timeout = setTimeout(() => {
                        // 改变执行上下文环境
                        func.apply(context, arguments)
                    }, wait)
                }
            }
        }


        // window.onscroll  = showTop;
        // window.onscroll  = debounce2(showTop,500);
        window.onscroll  = throttle2(showTop,500);


    </script>
</body>
</html>
